package colin.project.sso.server.config;

import colin.project.sso.server.common.util.SpringUtils;
import colin.project.sso.server.mvc.basic.LocalTokenManager;
import colin.project.sso.server.mvc.basic.RedisCache;
import colin.project.sso.server.mvc.basic.RedisTokenManager;
import colin.project.sso.server.mvc.basic.TokenManager;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import redis.clients.jedis.JedisPoolConfig;

/**
 * @Author joker
 * @Title MvcResourceConfig
 * @Description
 * @Date 2019/5/22 9:02 PM
 * @Since
 * @Version 1.0.0
 */
@Configuration
public class MvcResourceConfig implements EnvironmentAware, BeanDefinitionRegistryPostProcessor {

    Environment environment;

    @Value("${redis.hostname}")
    private String redisHostname;

    @Value("${redis.port}")
    private int redisPort;

    @Value("${redis.database}")
    private int redisDatabase;

    @Value("${redis.password}")
    private String redisPassword;

    /**
     * Set the {@code Environment} that this component runs in.
     *
     * @param environment
     */
    @Override
    public void setEnvironment(Environment environment) {
        environment = environment;
    }

    @Bean(name = "tokenManager")
    public TokenManager initTokenManager() {
        TokenManager tokenManager = null;
        if (SpringUtils.isDevEnv(environment)) {
            tokenManager = new LocalTokenManager();
        } else {
            tokenManager = new RedisTokenManager();
        }
        return tokenManager;
    }

    /**
     * Modify the application context's internal bean definition registry after its
     * standard initialization. All regular bean definitions will have been loaded,
     * but no beans will have been instantiated yet. This allows for adding further
     * bean definitions before the next post-processing phase kicks in.
     *
     * @param registry the bean definition registry used by the application context
     * @throws BeansException in case of errors
     */
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

    }

    /**
     * Modify the application context's internal bean factory after its standard
     * initialization. All bean definitions will have been loaded, but no beans
     * will have been instantiated yet. This allows for overriding or adding
     * properties even to eager-initializing beans.
     *
     * @param beanFactory the bean factory used by the application context
     * @throws BeansException in case of errors
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        if (!SpringUtils.isDevEnv(environment)) {
            RedisTemplate redisTemplate = initRedisTemplate();
            beanFactory.registerSingleton("redisTemplate", redisTemplate);
            RedisTemplate redisTemplateContains = (RedisTemplate) beanFactory.getBean("redisTemplate");
            if (null == redisTemplateContains) {
                throw new IllegalArgumentException("无法找到redisTemplate对象!");
            }
            RedisCache redisCache = initRedisCache(redisTemplateContains);
            beanFactory.registerSingleton("redisCache", redisCache);
        }
    }

    /**
     * 初始化redis链接
     *
     * @return
     */
    private JedisConnectionFactory initJedisConnectionFactory() {
        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
        jedisConnectionFactory.setHostName(redisHostname);
        jedisConnectionFactory.setPort(redisPort);
        jedisConnectionFactory.setDatabase(redisDatabase);
        if (!StringUtils.isEmpty(redisPassword)) {
            jedisConnectionFactory.setPassword(redisPassword);
        }
        jedisConnectionFactory.setPoolConfig(new JedisPoolConfig());
        return jedisConnectionFactory;
    }

    /**
     * @return
     */
    private RedisTemplate initRedisTemplate() {
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(initJedisConnectionFactory());
        return redisTemplate;
    }

    /**
     * 初始化RedisCache
     *
     * @param redisTemplate
     * @return
     */
    private RedisCache initRedisCache(RedisTemplate redisTemplate) {
        RedisCache redisCache = new RedisCache();
        redisCache.setRedisTemplate(redisTemplate);
        return redisCache;
    }
}
